#include "TCPServer.h"
#include "../common/util.h"
#include <cstring>

extern "C"
{
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
}

namespace qy
{

TCPServer::TCPServer(int port)
: m_port(port)
{
	struct sockaddr_in sa;
	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = htonl(INADDR_ANY);
	sa.sin_port = htons(port);

	m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(m_sock < 0)
	{
		fatal("unable to create socket");	
	}

	if(bind(m_sock, (struct sockaddr*)&sa, sizeof(sa)) < 0)
	{
		fatal("bind failed");
	}
}

TCPServer::~TCPServer()
{
	close();
}

bool TCPServer::listen(int queueSize)
{
	int ret = ::listen(m_sock, queueSize);
	return ret >= 0;
}

int TCPServer::accept()
{
	if(m_sock < 0)
	{
		return -1;
	}
	int sock = ::accept(m_sock, NULL, 0);
	if(sock != -1)
	{
		struct sockaddr_in sa;
		socklen_t saLen = sizeof(sa);
		if(getpeername(sock, (struct sockaddr*)&sa, &saLen) == 0)
		{
			char ip[65];	
			const char *p = inet_ntop(sa.sin_family, &(sa.sin_addr.s_addr), ip, 64);
			if(p)
			{
				log_sys("Accept a connection from %s", ip);
			}
		}
	}
	return sock;
}

void TCPServer::close()
{
	if(m_sock >= 0)
	{
		::close(m_sock);
	}
}

bool TCPServer::fail()
{
	return m_sock < 0;
}

}

